﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.IO;
using Microsoft.Win32;
using BesAsm.Stormwater.Swmm5Results;

namespace BesAsm.Stormwater.Swmm5ResultsUi.Presentation.Views
{
  /// <summary>
  /// Interaction logic for Swmm5ResultsHome.xaml
  /// </summary>
  public partial class Swmm5ResultsHome : Page
  {
    private SimulationResults _simResults;

    private Dictionary<string, CheckBox> _selectedLinkVariables =
       new Dictionary<string, CheckBox>();
    private Dictionary<string, CheckBox> _selectedNodeVariables =
      new Dictionary<string, CheckBox>();
    private Dictionary<string, CheckBox> _selectedCatchmentVariables =
      new Dictionary<string, CheckBox>();

    private BackgroundWorker _worker;
    private ProgressDialog _pd;

    public Swmm5ResultsHome()
    {
      InitializeComponent();

    }

    public Swmm5ResultsHome(SimulationResults simResults)
      : this()
    {
      _simResults = simResults;

      BindControls();
      BuildVariableDictionaries();


    }

    private void BuildVariableDictionaries()
    {
      _selectedLinkVariables.Add("FlowRate", chkLinkFlowRate);
      _selectedLinkVariables.Add("FlowDepth", chkLinkFlowDepth);
      _selectedLinkVariables.Add("Velocity", chkLinkVelocity);
      _selectedLinkVariables.Add("FroudeNumber", chkLinkFroudeNumber);
      _selectedLinkVariables.Add("Capacity", chkLinkCapacity);
      _selectedNodeVariables.Add("Depth", chkNodeDepth);
      _selectedNodeVariables.Add("HydraulicHead", chkNodeHydraulicHead);
      _selectedNodeVariables.Add("VolumeStoredAndPonded", chkNodeVolumeStored);
      _selectedNodeVariables.Add("LateralInflow", chkNodeLateralInflow);
      _selectedNodeVariables.Add("TotalInflow", chkNodeTotalInflow);
      _selectedNodeVariables.Add("FlowLostToFlooding", chkNodeFlooding);
      _selectedCatchmentVariables.Add("Rainfall", chkCatchmentRainfall);
      _selectedCatchmentVariables.Add("SnowDepth", chkCatchmentSnowDepth);
      _selectedCatchmentVariables.Add("EvaporationAndInfiltration", chkCatchmentEtAndInfiltration);
      _selectedCatchmentVariables.Add("RunoffRate", chkCatchmentRunoffRate);
      _selectedCatchmentVariables.Add("GroundwaterOutflowRate", chkCatchmentGroundwaterFlow);
      _selectedCatchmentVariables.Add("GroundwaterWaterTable", chkCatchmentWaterTable);
    }

    private void BindControls()
    {
      lstLinks.ItemsSource = _simResults.Links;
      lstLinks.DisplayMemberPath = "Name";

      lstNodes.ItemsSource = _simResults.Nodes;
      lstNodes.DisplayMemberPath = "Name";

      lstCatchments.ItemsSource = _simResults.Catchments;
      lstCatchments.DisplayMemberPath = "Name";

      txtSimStartDate.Text = _simResults.StartDate.ToString("MMMM dd, yyyy");
      txtSimEndDate.Text = _simResults.EndDate.ToString("MMMM dd, yyyy");

      datePickerStart.SelectedDate = _simResults.StartDate;
      datePickerEnd.SelectedDate = _simResults.EndDate;
      timePickerStart.SelectedTime = new TimeSpan(_simResults.StartDate.Hour, _simResults.StartDate.Minute, 0);
      timePickerEnd.SelectedTime = new TimeSpan(_simResults.EndDate.Hour, _simResults.EndDate.Minute, 0);

      ICollectionView view;
      view = CollectionViewSource.GetDefaultView(lstLinks.ItemsSource);
      new TextSearchFilter(view, txtFilterLinks);

      view = CollectionViewSource.GetDefaultView(lstNodes.ItemsSource);
      new TextSearchFilter(view, txtFilterNodes);

      view = CollectionViewSource.GetDefaultView(lstCatchments.ItemsSource);
      new TextSearchFilter(view, txtFilterCatchments);

    }

    private void btnLoadResults_Click(object sender, RoutedEventArgs e)
    {
      Page detailPage = new Swmm5ResultsDetail(_simResults);
      NavigationService.Navigate(detailPage);
    }

    private void btnExportLinkResults_Click(object sender, RoutedEventArgs e)
    {
      SaveFileDialog sfd = new SaveFileDialog();
      sfd.Filter = "CSV File|*.csv|All Files|*.*";
      sfd.FileName = _simResults.Name + "_link_results.csv";
      if (sfd.ShowDialog() != true)
        return;

      string file = sfd.FileName;

      List<ResultVariablesBase> links =
        lstLinks.SelectedItems.Cast<ResultVariablesBase>().ToList();
      List<string> vars = _selectedLinkVariables
       .Where(p => p.Value.IsChecked ?? false)
       .Select(p => p.Key)
       .ToList();

      ExportResults(file, links, vars);
    }

    private void btnExportNodes_Click(object sender, RoutedEventArgs e)
    {
      SaveFileDialog sfd = new SaveFileDialog();
      sfd.Filter = "CSV File|*.csv|All Files|*.*";
      sfd.FileName = _simResults.Name + "_nodes_results.csv";
      if (sfd.ShowDialog() != true)
        return;

      string file = sfd.FileName;

      List<ResultVariablesBase> nodes =
        lstNodes.SelectedItems.Cast<ResultVariablesBase>().ToList();
      List<string> vars = _selectedNodeVariables
       .Where(p => p.Value.IsChecked ?? false)
       .Select(p => p.Key)
       .ToList();

      ExportResults(file, nodes, vars);
    }

    private void btnExportCatchments_Click(object sender, RoutedEventArgs e)
    {
      SaveFileDialog sfd = new SaveFileDialog();
      sfd.Filter = "CSV File|*.csv|All Files|*.*";
      sfd.FileName = _simResults.Name + "_catchment_results.csv";
      if (sfd.ShowDialog() != true)
        return;

      string file = sfd.FileName;

      List<ResultVariablesBase> catchments =
        lstCatchments.SelectedItems.Cast<ResultVariablesBase>().ToList();
      List<string> vars = _selectedCatchmentVariables
        .Where(p => p.Value.IsChecked ?? false)
        .Select(p => p.Key)
        .ToList();

      ExportResults(file, catchments, vars);
    }

    private void ExportResults(string file, List<ResultVariablesBase> elements, List<string> vars)
    {
      ResultsExporter exporter = new ResultsExporter(_simResults);
      exporter.OutputInterval = GetOutputInterval();
      exporter.StartDate = datePickerStart.SelectedDate + timePickerStart.SelectedTime;
      exporter.EndDate = datePickerEnd.SelectedDate + timePickerEnd.SelectedTime;

      _worker = new BackgroundWorker();
      BackgroundWorker worker = _worker;
      worker.WorkerReportsProgress = true;
      worker.WorkerSupportsCancellation = true;
      worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
      worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
      exporter.PrepareWriteResultsAsync(file, elements, vars, worker);
      worker.RunWorkerAsync();

      System.Windows.Interop.WindowInteropHelper helper = new System.Windows.Interop.WindowInteropHelper(Window.GetWindow(this));
      _pd = new ProgressDialog(helper.Handle);
      _pd.Maximum = 100;
      _pd.Title = "Exporting results";
      _pd.Line1 = "Line 1";
      _pd.Line2 = "Line 2";
      _pd.Line3 = "Line 3";
      _pd.Value = 0;
      _pd.ShowDialog(ProgressDialog.PROGDLG.Modal, ProgressDialog.PROGDLG.AutoTime, ProgressDialog.PROGDLG.NoMinimize);
    }

    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
      _pd.CloseDialog();

      if (e.Error != null)
      {
        if (e.Error.GetType() == typeof(OperationCanceledException))
          return;

        MessageBox.Show(e.Error.Message, "Error exporting results", MessageBoxButton.OK, MessageBoxImage.Error);
        return;
      }

      MessageBox.Show("Results file written succesfully!", "Success", MessageBoxButton.OK, MessageBoxImage.Asterisk);
      return;

      if (MessageBox.Show(
        "Results written. Open file using default application?", "Success",
        MessageBoxButton.YesNo, MessageBoxImage.Question)
        == MessageBoxResult.Yes)
      {
        System.Diagnostics.Process.Start("yo");
      }
    }

    void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
      if (_pd.HasUserCancelled)
      {
        _worker.CancelAsync();
        _pd.CloseDialog();
      }

      _pd.Value = (uint)e.ProgressPercentage;
      _pd.Line2 = "Read " + e.ProgressPercentage + "%";
    }

    private TimeSpan GetOutputInterval()
    {
      ComboBoxItem cbi = (ComboBoxItem)cmbReportingInterval.SelectedItem;

      switch ((string)cbi.Content)
      {
        case "Daily":
          return new TimeSpan(1, 0, 0, 0);
        default:
          return _simResults.Interval;
      }
    }

    private void PlotResults(List<ResultVariablesBase> elements, List<string> vars)
    {
      DateTime? startDate = datePickerStart.SelectedDate + timePickerStart.SelectedTime;
      DateTime? endDate = datePickerEnd.SelectedDate + timePickerEnd.SelectedTime;

      chart.Series.Clear();

      foreach (ResultVariablesBase rvb in elements)
      {
        foreach (string s in vars)
        {
          ResultVariable rv = rvb[s];
          if (rv == null || !rv.IsLoaded)
          {
            rvb.Load(s, false, startDate.Value, endDate.Value);
            rv = rvb[s];
          }

          Infragistics.Windows.Chart.Series series = new Infragistics.Windows.Chart.Series();
          series.DataSource = rv;
          series.Label = rvb.Name + "_" + rv.Name;
          series.Name = rvb.Name + "_" + rv.Name;
          series.ChartType = Infragistics.Windows.Chart.ChartType.ScatterLine;
          series.DataMapping = "ValueX=Key; ValueY=Value";
          chart.Series.Add(series);
        }
        rvb.Close();          
      }

    }

    private void btnPlotLinks_Click(object sender, RoutedEventArgs e)
    {
      List<ResultVariablesBase> links =
        lstLinks.SelectedItems.Cast<ResultVariablesBase>().ToList();
      List<string> vars = _selectedLinkVariables
       .Where(p => p.Value.IsChecked ?? false)
       .Select(p => p.Key)
       .ToList();

      PlotResults(links, vars);
    }

  }
}
